const { SerialPort } = require('serialport')
const { DelimiterParser } = require('@serialport/parser-delimiter')
// 导入日志模块
const logger = require('./log-winston.js')
// 导入sleep函数
const sleep = require('./utils/sleep.js')
// 导入定位解析函数合集
const ps = require('./pasers/mainParser.js')
// 导入自定义指令
const customOrder = require('./orderList/customOrder.js')
// 检测bd是否有信息输入
let flagCount = new Date().getTime()
// 获取串口列表函数，找到wit差分串口
async function getPortList() {
	let ports
	let wit_port = []
	while (true) {
		ports = await SerialPort.list()
		ports.forEach((item) => {
			if (item.manufacturer === 'wch.cn') {
				wit_port.push(item.path)
			}
		})
		if (wit_port.length > 0) {
			return wit_port
		} else {
			console.log('扫描串口，无wit串口，等待5秒重新打开...')
			await sleep(5000)
			continue
		}
	}
}
// 获取北斗短报文串口列表
async function getBdPortList() {
	let bd_port = ["COM1"]
	// 由于是通用串口无法扫描所以直接"COM1"
	return bd_port
}
// 持续发送消息检测串口是否被拔出~~~~有风险~~~定时器在最底部
let chabaErrorFlag_wit = false
let chabaErrorFlag_bd = false
// 打开/关闭定时器启动端口-如果打开串口失败则隔2秒继续打开
let timer_wit = null
function startTimer_wit(port) {
	timer_wit = setInterval(function () {
		port.open((err) => {
			if (err) {
				console.log('wit再次打开串口失败!')
			} else {
				// 重新打开后这个也打开
				chabaErrorFlag_wit = true
				stopTimer_wit()
			}
		})
	}, 2000)
}
function stopTimer_wit() {
	clearInterval(timer_wit)
	timer_wit = null
}
let timer_bd = null
function startTimer_bd(port) {
	timer_bd = setInterval(function () {
		port.open((err) => {
			if (err) {
				console.log('bd再次打开串口失败!')
			} else {
				// 重新打开后这个也打开
				chabaErrorFlag_bd = true
				stopTimer_bd()
			}
		})
	}, 2000)
}
function stopTimer_bd() {
	clearInterval(timer_bd)
	timer_bd = null
}

/**
 * 读取配置并初始化串口，以及接受数据事件函数配置
 */
async function init_port() {
	/* ~~~~~~~~~~~~wit_port~~~~~~~~~~~~ */
	// 得到wit串口数组，使用数组第一个串口进行占用
	const wit_port_list = await getPortList()
	// 创建wit占用串口
	const port_wit = new SerialPort(
		{
			path: wit_port_list[0],
			baudRate: 230400,
			parity: 'none',
		},
		(err) => {
			if (err) {
				console.log('wit串口打开失败!')
				// 如果打开失败则继续打开
				startTimer_wit(port_wit)
			} else {
				console.log('wit串口打开成功!')
				// 打开成功后把标志改了
				chabaErrorFlag_wit = true
			}
		}
	)
	const parser_wit = port_wit.pipe(new DelimiterParser({ delimiter: '\r\n' }))
	parser_wit.on('data', (data) => {
		ps.mainParse(data)
	})

	/* ~~~~~~~~~~~~bd_port~~~~~~~~~~~~ */
	const bd_port_list = await getBdPortList()
	// 创建bd占用串口
	const port_bd = new SerialPort(
		{
			path: bd_port_list[0],
			baudRate: 115200,
			parity: 'none',
		},
		(err) => {
			if (err) {
				console.log('bd串口打开失败!')
				// 如果打开失败则继续打开
				startTimer_bd(port_bd)
			} else {
				console.log('bd串口打开成功!')
				// 打开成功后把标志改了
				chabaErrorFlag_bd = true
			}
		}
	)
	const parser_bd = port_bd.pipe(new DelimiterParser({ delimiter: '\r\n' }))
	parser_bd.on('data', (data) => {
		ps.bdParse(data, port_bd)
		flagCount = new Date().getTime()
	})

	// 2.总体错误捕获
	port_wit.on('error', (err) => {
		console.log('wit捕获总体错误:', err)
	})
	port_bd.on('error', (err) => {
		console.log('bd捕获总体错误:', err)
	})
	// 3.注册打开串口事件，只执行一次，最先执行
	port_wit.on('open', () => {
		console.log('wit串口打开了:open事件!')
		chabaErrorFlag_wit = true
		stopTimer_wit()
	}) -
		port_bd.on('open', () => {
			console.log('bd串口打开了:open事件!')
			chabaErrorFlag_bd = true
			stopTimer_bd()
		})
	return { port_wit, port_bd }
}

/* 初始化程序函数 */
async function main() {
	const { port_wit, port_bd } = await init_port()
	// 关闭bd蓝牙模块
	port_bd.write(customOrder.closeBluet)
	port_bd.drain(() => {
		console.log('bd蓝牙模块关闭...')
	})
	// 关闭定位模块串口输出
	port_bd.write(customOrder.openShortModuleSerial)
	port_bd.drain(() => {
		console.log('bd定位模块短报文串口输出关闭，开启短报文串口输出...')
	})
	// 检测是否10秒内务数据输入，则重新打开短报文模块
	setInterval(function () {
		let currentTime = new Date().getTime()
		if (currentTime - flagCount > 10000) {
			port_bd.write(customOrder.openShortModule)
			port_bd.drain(() => {
				console.log('bd尝试重新打开短报文模块!')
			})
			setTimeout(() => {
				port_bd.write(customOrder.openShortModuleSerial)
				port_bd.drain(() => {
					console.log('bd尝试重新打开短报文模块串口输出的指令发出...')
				})
			}, 500)
		}
	}, 10000)
	// 心跳函数wit
	setInterval(async function () {
		if (!port_wit.isOpen && chabaErrorFlag_wit) {
			port_wit.open((err) => {
				if (err) {
					console.log('wit您还未插上wit串口,请检查线缆链接情况...')
				} else {
					console.log('wit重启wit串口成功...success')
					port_wit.flush((err) => {
						if (err) {
							console.log('wit清除缓存失败,请检查!')
						} else {
							console.log('wit重新插拔清除buffer缓存!')
						}
					})
				}
			})
		}
	}, 10 * 1000)
	// 心跳函数bd
	setInterval(async function () {
		if (!port_bd.isOpen && chabaErrorFlag_bd) {
			port_bd.open((err) => {
				if (err) {
					console.log('bd您还未插上bd串口,请检查线缆链接情况...')
				} else {
					console.log('bd重启bd串口成功...success')
					port_bd.flush((err) => {
						if (err) {
							console.log('bd清除缓存失败,请检查!')
						} else {
							console.log('bd重新插拔清除buffer缓存!')
						}
					})
				}
			})
		}
	}, 10 * 1000)
}
main()
